home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 July / Macworld (1999-07).dmg / Shareware World / Info / For Developers / Mops 3.4.sea / Mops source / PPC source / zPEF < prev    next >
Text File  |  1998-09-20  |  28KB  |  1,132 lines

  1. (*        =========================================================
  2.                           PEF file generation
  3.         =========================================================
  4.         
  5. This file handles the writing out of a PEF object file for our compiled
  6. PPC code.
  7.  
  8. It has more features than cg4, since that only had one job to do - to
  9. write out the initial PPC target image.
  10.  
  11. *)
  12.  
  13. forward  write_to_container
  14.  
  15. 0    value    CONTAINER_OFFS
  16. 0    value    CHOP_HERE
  17.  
  18. 0    value    MAIN_CODE_SIZE
  19. 0    value    SEG_CODE_SIZE
  20. 0    value    CODE_OFFS
  21.  
  22. 0    value    MAIN_DATA_SIZE
  23. 0    value    SEG_DATA_SIZE
  24. 0    value    DATA_OFFS
  25.  
  26. \ spare_code_size and spare_data_size are in setup
  27.  
  28. 0    value    LDR_SIZE
  29. 0    value    LDR_OFFS
  30.  
  31. false    value    shared_lib?            \ set true if we're generating a shared
  32.                                     \  library
  33.  
  34. 80    constant    INFO_BLOCK_SIZE        \ a block of useful info we put at the
  35.                                     \  start of the code section so our PPC
  36.                                     \  code can pick it up easily.
  37.                                     
  38. 4    constant    hash_table_power    \ #elements in exports hash table is
  39.                                     \  2**hash_table_power.  Each element is 4 bytes.
  40.  
  41. 4  hash_table_power <<
  42.     constant    hash_table_size
  43.  
  44.  
  45. 23    constant    #IMPORTED_SYMBOLS
  46.                     \ We define this as a constant since we need it at
  47.                     \  compile time.  In init_import_sym_tbl below, called
  48.                     \  at write_PEF time, we check that the real number of
  49.                     \  imported symbols agrees, and bail out if it doesn't.
  50.                     \  That avoids nasty crashes.
  51.  
  52. 0    value        #EXPORTED_SYMBOLS
  53. 0    value        hash_info_len        \ hash table + key table + symbol table
  54.  
  55. #imported_symbols 4*
  56.     constant    ENTRY_POINT_TOC_OFFSET
  57.                     \ our entry point descriptor comes straight after
  58.                     \  the imported symbols, which are 4 bytes each
  59.  
  60.  
  61.     bytestring                ldr_import_sym_tbl
  62.     bytestring                relocs
  63.     bytestring                export_relocs
  64.     bytestring                loader_strings
  65.     bytestring                $cfrg
  66.     bytestring                $threads
  67. 16    bytestring_array        export_key_table
  68. 16    bytestring_array        exported_symbol_table
  69.  
  70.  
  71.  
  72. \        =============  resource stuff ===============
  73.  
  74. \ (mainly lifted from InstlMod.txt)
  75.  
  76.  
  77. syscall ResError
  78. syscall ChangedResource
  79. syscall AddResource
  80. syscall RemoveResource
  81. syscall CurResFile
  82. syscall UseResFile
  83.  
  84. : resChk
  85.     ResError  ?dup
  86.     IF  db 3 beep  3 beep  cr
  87.         dup -48 =
  88.         IF    ." You can't save using the same name as the running" cr
  89.             ." application.  Please try again with a different name." cr
  90.         ELSE
  91.             ." Res error# " .  cr
  92.         THEN
  93.         QUIT
  94.     THEN  ;
  95.  
  96.  
  97. \ Class RES+ adds methods to Resource to allow various modifications
  98. \ to resources.  We'll put more in as we need them.
  99.  
  100. :class    RES+    super{ resource }
  101.  
  102. objPtr    TEMPRES  class_is  res+
  103.  
  104. :m CHANGED:    get: self  ChangedResource  ;m
  105.  
  106. :m ADDRES:  { s255 -- }
  107.     get: self
  108.     get: resType  get: ID
  109.     s255  AddResource  resChk  ;m
  110.  
  111. ;class
  112.  
  113.  
  114. res+    srcres
  115. res+    dstres
  116.  
  117. : copyres    \ ( type resID -- )  Copies the resource by copying
  118.             \  the handle's data in memory.  Use this one for resources
  119.             \  currently in use.
  120.             
  121.     2dup  set: srcRes  set: dstRes
  122.     getnew: srcRes  resChk  srcRes ->: dstRes
  123.     nullOSstr  addRes: dstRes  resChk  ;
  124.  
  125.  
  126. \        ===============================================================
  127.  
  128. \ Before writing the PEF, if we're installing, we have to make sure
  129. \  all needed modules are loaded.
  130.  
  131. : (LDMOD)  { theCfa dummy \ modObj -- }
  132.     theCfa  mod? NIF  drop  EXIT  THEN
  133.     >obj  -> modObj
  134.  
  135.     install?: [ modObj ]  IF  load: [ modObj ]  THEN
  136. ;
  137.  
  138. : LOAD_MODS        \ Loads the modules
  139.     false -> instld?        \ so the modules will load!!
  140.     ['] (ldmod)  0 trav
  141.     true -> instld?            \ restore
  142. ;
  143.  
  144.  
  145. \        ===============================================================
  146.  
  147.  
  148. :class  SECTION_HEADER  super{ object }
  149. record
  150. {    var        nameOffset
  151.     var        defaultAddress
  152.     var        totalSize
  153.     var        unpackedSize
  154.     var        packedSize
  155.     var        containerOffset
  156.     ubyte    sectionKind
  157.     ubyte    alignment
  158.     ubyte    shareKind
  159.     ubyte    reservedA
  160. }
  161.  
  162. :m CLASSINIT:
  163.     -1 put: nameOffset  ;m        \ means no name
  164.     
  165. :m >SIZES:  ( totalSize initializedSize -- )
  166.     dup put: packedSize put: unpackedSize    \ we don't use PIdata, so
  167.                                             \  these 2 are the same
  168.     put: totalSize
  169. \    get: sectionKind 4 =            \ loader section?
  170. \    IF    clear: execSize
  171. \        clear: initSize
  172. \    THEN
  173. ;m
  174.  
  175. :m >KIND: { kind -- }
  176.     kind  put: sectionKind
  177.     kind 1 =  kind 2 = or
  178.     IF                        \ data or PIdata
  179.             1                \ contextShare
  180.     ELSE    4                \ globalShare
  181.     THEN
  182.     put: shareKind
  183.     4 put: alignment
  184. ;m
  185.  
  186. :m >OFFSET:        put: containerOffset  ;m
  187.  
  188. :m INIT:    \ ( offset totalSize initializedSize -- )
  189.     >sizes: self  put: containerOffset  ;m
  190.  
  191. ;class
  192.  
  193. \        ================== loader section stuff ===================
  194.  
  195. :class  LOADER_HEADER_CLASS  super{ object }
  196. record
  197. {    var        mainSection                \ sect containing main (initial ent pt) desc 
  198.                                     \  (we use 1)
  199.     var        mainOffset                \ offs in sect where desc is
  200.     var        initSection                \    ditto for init point desc
  201.     var        initOffset
  202.     var        termSection                \    ditto for term point desc
  203.     var        termOffset
  204.     var        importedLibraryCount
  205.     var        totalImportedSymbolCount
  206.     var        relocSectionCount        \ number of relocation headers
  207.     var        relocInstrOffset
  208.     var        loaderStringsOffset
  209.     var        exportHashOffset
  210.     var        exportHashTablePower
  211.     var        exportedSymbolCount
  212. }
  213.  
  214. :m INIT:  { relocTblOffs stringsOffs hashSlotTblOffs entrySect -- }
  215.     relocTblOffs    put: relocInstrOffset
  216.     stringsOffs        put: loaderStringsOffset
  217.     hashSlotTblOffs    put: exportHashOffset
  218.     entrySect        put: mainSection
  219.     
  220.     #imported_symbols        put: totalImportedSymbolCount
  221.     #exported_symbols        put: exportedSymbolCount
  222.     entry_point_toc_offset    put: mainOffset
  223.     shared_lib?
  224.     IF    1 put: initSection
  225.         entry_point_toc_offset    put: initOffset
  226.     THEN
  227. ;m
  228.  
  229. :m CLASSINIT:
  230.     1  put: mainSection            \ change to -1 for shared libs - no main routine
  231.     -1 put: initSection            \ need to use an initialization routine
  232.                                 \  for shared libs, so we'll change to 1 here
  233.     -1 put: termSection            \ and maybe a term routine too
  234.     1 put: importedLibraryCount    \ should only be 1 ("InterfaceLib") for Mops PEFs
  235.     1 put: relocSectionCount    \ Only 1 loader relocation header
  236.     hash_table_power  put: exportHashTablePower
  237. ;m
  238.     
  239. ;class
  240.  
  241.  
  242. : hash_for_PEF  { addr len \ hashValue hash_word hash_index c -- hash_word hash_index }
  243.     0 -> hashValue
  244.  
  245.     len 0 ?DO
  246.         addr i + c@ -> c
  247.         hashValue 1 <<
  248.         hashValue 16 >> -
  249.         c xor  -> hashValue
  250.     LOOP
  251.     len 16 <<
  252.     hashValue dup 16 >> xor  $ ffff and  or
  253.     -> hash_word
  254.  
  255.     hash_word
  256.     hash_word hash_table_power >>  xor
  257.     1  hash_table_power << 1-  and  -> hash_index
  258.     hash_word  hash_index
  259. ;
  260.     
  261.  
  262. :class  EXPORT_HASH_TABLE_CLASS  super{ object }
  263.  
  264.     hash_table_size        bytes    theTable
  265.  
  266. :m write:
  267.     addr: theTable  hash_table_size  write_to_container
  268.     16 0 DO
  269.         i select: export_key_table
  270.         all: export_key_table  write_to_container
  271.     LOOP
  272.     16 0 DO
  273.         i select: exported_symbol_table
  274.         all: exported_symbol_table  write_to_container
  275.     LOOP
  276. ;m
  277.  
  278. :m setup:  { \ index chn_cnt -- }
  279.  
  280.             \ called when there are no more export symbols to be added,
  281.             \  but before we write anything out.  Sets up theTable
  282.             \  according to what we've accumulated in the bytestring_arrays.
  283.  
  284.     hash_table_size  -> hash_info_len
  285.     0 -> index
  286.     16 0 DO
  287.         i select: export_key_table
  288.         reset: export_key_table
  289.         len: export_key_table  dup ++> hash_info_len
  290.         ?dup
  291.         IF    4/ -> chn_cnt             \ chain count for this hash slot
  292.             chn_cnt 18 <<  index or
  293.             addr: theTable i 4* +  !
  294.             chn_cnt ++> index
  295.         THEN
  296.     LOOP
  297.  
  298.     16 0 DO
  299.         i select: exported_symbol_table
  300.         reset: exported_symbol_table
  301.         len: exported_symbol_table  ++> hash_info_len
  302.     LOOP
  303. ;m
  304.  
  305. :m add_symbol:  { addr len val \ hash_word hash_index -- }
  306.  
  307. \ first we do the hash and select the right element in the
  308. \  bytestring_arrays:
  309.  
  310.     addr len  hash_for_PEF  -> hash_index  -> hash_word
  311.  
  312.     hash_index  select: exported_symbol_table
  313.     hash_index  select: export_key_table
  314.     
  315.     hash_word  +L: export_key_table
  316.     pos: loader_strings
  317.     $ 02000000 or                    \ means it's a standard procedure pointer
  318.                                     \  i.e. points to a transfer vector
  319.     +L: exported_symbol_table
  320.     addr len add: loader_strings    \ and we don't need a 0 at the end
  321.     val +L: exported_symbol_table
  322.     1 +W: exported_symbol_table        \ it's in section 1 (data - it's a transfer vect)
  323. ;m
  324.  
  325. :m clear:
  326.     addr: theTable  hash_table_size  erase  ;m
  327.  
  328. ;class
  329.  
  330.  
  331. \        ===========================================================
  332.  
  333.  
  334. :class  IMP_FILES_SUBSEC_CLASS  super{ object }
  335. record
  336. {    var        fileName
  337.     var        oldDefVersion
  338.     var        currentVersion
  339.     var        numImports
  340.     var        impFirst
  341.     ubyte    initBefore
  342.     ubyte    reservedB
  343.     uint    reservedH
  344. }
  345.  
  346. :m >numImports:        put: numImports  ;m
  347.  
  348. ;class
  349.  
  350.  
  351. :class  PEF_HEADER_CLASS  super{ object }
  352. record
  353. {    var        joy
  354.     var        fileTypeID
  355.     var        architectureID
  356.     var        versionNumber
  357.     var        dateTimeStamp
  358.     var        definVersion
  359.     var        implVersion
  360.     var        currentVersion
  361.     uint    numberSections
  362.     uint    loadableSections
  363.     var        memoryAddress
  364. }
  365.  
  366. :m CLASSINIT:
  367.     'type    Joy!  put: joy
  368.     'type    peff  put: fileTypeID
  369.     'type    pwpc  put: architectureID
  370.     1  put: versionNumber
  371.     3  put: numberSections
  372.     2  put: loadableSections
  373. ;m
  374.  
  375. :m SETTIMESTAMP:
  376. \    $ 20C @                        \ ### fix after I can handle fetch from a
  377.                                 \  literal address!
  378.     0  put: dateTimeStamp  ;m
  379.  
  380. ;class
  381.  
  382. :class    cfrg_ClASS  super{ object }
  383. record
  384. {    var        res0
  385.     var        res1
  386.     var        cfrgVersion
  387.     var        res2
  388.     var        res3
  389.     var        res4
  390.     var        res5
  391.     var        #fragDescs
  392.     
  393. \ now the (only) fragment description:
  394.     var        CodeType
  395.     var        UpdateLevel
  396.     var        CurrentVersion
  397.     var        OldestDevVersion
  398.     var        AppStackSize
  399.     uint    AppLibDirectory
  400.     ubyte    TypeOfFragment
  401.     ubyte    LocationOfFragment
  402.     var        OffsetToFragment
  403.     var        LengthOfFragment
  404.     var        res6
  405.     var        res7
  406. }
  407.  
  408. :m CLASSINIT:
  409.     1 put: cfrgVersion
  410.     1 put: #fragDescs
  411.     'type pwpc  put: codeType
  412.     1 put: TypeOfFragment
  413.     1 put: LocationOfFragment
  414. \ everything else except LenOfInfoRec stays zero.
  415. ;m
  416.  
  417. ;class
  418.  
  419.  
  420.     cfrg_class                my_cfrg
  421.  
  422.     PEF_header_class        PEF_header
  423.     section_header            CODE_SECT_HDR
  424.     section_header            DATA_SECT_HDR
  425.     section_header            LOADER_SECT_HDR
  426.  
  427.     loader_header_class        LOADER_HEADER
  428.     export_hash_table_class    EXPORT_HASH_TABLE
  429.  
  430. \ we only have one import file - for more, we'd need to have more
  431. \  than one imp_files_subsec_class object.  But note, there's only
  432. \  one import symbol table per PEF.
  433.  
  434.     imp_files_subsec_class    IMPORT_FILES_SUBSECTION
  435.     
  436.  
  437. variable  PAD_BYTES  16 reserve
  438.  
  439. : ALIGN_IN_CONTAINER  { alignment# \ pad# -- }
  440.     alignment#  container_offs  alignment# 1- and  -
  441.     alignment# 1-  and  -> pad#
  442.     pad#  0EXIT
  443.     pad_bytes pad#  write: ffcb  OK?
  444.     pad# ++> container_offs
  445. ;
  446.  
  447. :f WRITE_TO_CONTAINER  { addr len -- }
  448.     addr len write: ffcb  OK?
  449.     len ++> container_offs
  450. ;f
  451.  
  452.  
  453. : WRITE_OBJ  { ^obj \ len -- }
  454.     length: [ ^obj ]  -> len
  455.     ^obj len  write_to_container
  456. ;
  457.  
  458.  
  459. : ADD_EXPORT_SYMBOL  { addr len val \ -- }
  460.  
  461.     addr len val  add_symbol: export_hash_table
  462.     1 ++> #exported_symbols
  463. ;
  464.  
  465.  
  466. : (exp)  { theCfa dummy \ addr -- }
  467.  
  468.     theCfa 2- -> addr
  469.     addr w@ $ BE05 <> ?EXIT
  470.     BEGIN
  471.         -4 ++> addr
  472.         addr w@ $ BF0C =
  473.     UNTIL
  474.     addr 4+ count                \ addr & len of case-sensitive name
  475.     DP  data_start -            \ offset of transfer vector in data section
  476.     add_export_symbol
  477.     theCfa dup
  478.     c@  $ 10 and                \ fp flags?
  479.     IF  6 +  ELSE  2+  THEN        \ get addr of first instruction of defn
  480.     code_start -  ,  0 ,
  481.                 \ initial TV has offsets to code to be executed, and data 
  482.                 \  section (latter offset is zero of course).
  483.     8 ++> main_data_size
  484.     $ 4600 +W: export_relocs    \ RelocTVector8 1 - this will update
  485.                                 \  the TV for this entry.
  486.  
  487. ;
  488.  
  489.  
  490. : get_exported_symbols
  491.     0 -> #exported_symbols
  492.     shared_lib?  0EXIT            \ if not a shared lib, don't worry about
  493.                                 \  exported symbols
  494.                                 
  495. \ before we pick up the exported symbols, we need to add a reloc op
  496. \  to set relocAddress to where we are in the data section.  This is
  497. \  the RelocSetPosition op.
  498.  
  499.     DP data_start -                \ data section offset
  500.     dup 16 >>  $ A000 or  +W: export_relocs  +W: export_relocs
  501.  
  502.     ['] (exp)  0 trav
  503. ;
  504.  
  505.  
  506.  
  507. 0    value    IMP_SYM_CNT
  508.  
  509. : ADD_IMPORT_SYMBOL        \ ( addr len -- )  symbol name is passed in.
  510.     pos: loader_strings
  511.     $ 02000000 or                    \ means it's a standard procedure pointer
  512.                                     \  i.e. points to a transfer vector
  513.     +L: ldr_import_sym_tbl
  514.     add: loader_strings  0 +: loader_strings
  515.     1 ++> imp_sym_cnt  ;
  516.  
  517.  
  518. \ Note the symbols we list here are CASE-SENSITIVE!!  The PEF will fail at startup
  519. \  time if something doesn't resolve, and case matters!
  520.  
  521.  
  522. : INIT_SYMBOLS
  523.     0 -> imp_sym_cnt
  524.     " InterfaceLib"  add: loader_strings  0 +: loader_strings
  525.  
  526.     " GetSharedLibrary"            add_import_symbol
  527.     " FindSymbol"                add_import_symbol
  528.     " Debugger"                    add_import_symbol
  529.     " NewHandleClear"            add_import_symbol
  530.     " NewPtrClear"                add_import_symbol
  531.     " MoveHHi"                    add_import_symbol
  532.     " HLock"                    add_import_symbol
  533.     " MakeDataExecutable"        add_import_symbol
  534.     " BlockMove"                add_import_symbol
  535.     " ExitToShell"                add_import_symbol
  536.     " InitGraf"                    add_import_symbol
  537.     " InitFonts"                add_import_symbol
  538.     " InitWindows"                add_import_symbol
  539.     " TEInit"                    add_import_symbol
  540.     " InitMenus"                add_import_symbol
  541.     " InitCursor"                add_import_symbol
  542.     " AEInstallEventHandler"    add_import_symbol
  543.     " GetNewWindow"                add_import_symbol
  544.     " SetPort"                    add_import_symbol
  545.     " NewRgn"                    add_import_symbol
  546.     " TextMode"                    add_import_symbol
  547.     " SysBeep"                    add_import_symbol
  548.     " MaxApplZone"                add_import_symbol
  549.  
  550. \ add any more we need here.
  551.  
  552.     imp_sym_cnt #imported_symbols <>  abort" wrong number of imported symbols"
  553.     #imported_symbols >numImports: import_files_subsection
  554.  
  555. (* *****  testing:
  556.     " jo"    20                    add_export_symbol
  557.     " aardvark"  48                add_export_symbol
  558.     " bloggs"    10                add_export_symbol
  559.     " q"    99                    add_export_symbol
  560.     " smith"    30                add_export_symbol
  561.     " sam"        80                add_export_symbol
  562.     " joe"        90                add_export_symbol
  563.     " somebodyOrOther"    40        add_export_symbol
  564.     " whatever"    50                add_export_symbol
  565.     " youveGotToBeKidding"    60    add_export_symbol
  566. **** *)
  567.  
  568.     get_exported_symbols
  569. ;
  570.  
  571.  
  572.  
  573. : TOC_SIZE    \ ( -- n )    4 bytes for each imported symbol, plus 8 for
  574.                     \    our entry point function descriptor, plus
  575.                     \    32 for saved regs
  576.     entry_point_toc_offset  40 +
  577. ;
  578.  
  579.  
  580.  
  581. \ Here we define some words so we can easily make a call to one of these
  582. \  symbols.  We do it here so we can be sure that the TOC offsets are
  583. \  right - these are determined by the above order.
  584.  
  585.  
  586. forward (TOC_CALL)
  587.  
  588. 0    value    curr_TOC_offset
  589.  
  590. : TOC_CALL
  591.     curr_TOC_offset  postpone literal  postpone (TOC_call)
  592.     4 ++> curr_TOC_offset  ;                immediate
  593.  
  594.  
  595.  
  596. : %_GetSharedLibrary
  597.     6 1  TOC_call  ;            immediate
  598.  
  599. : %_FindSymbol
  600.     4 1  TOC_call  ;            immediate
  601.  
  602. \ we don't define a %_Debugger - we don't want regs monkeyed with when we
  603. \  call it, so we just hand-wind the calling sequence (at DBGR in cg6).
  604. \ We do, however need the next TOC offset (8) for the symbol "Debugger".
  605.  
  606. 12 -> curr_TOC_offset            \ skip offset 8 (Debugger)
  607.  
  608. : %_NewHandleClear
  609.     1 1  TOC_call  ;        immediate
  610.  
  611. : %_NewPtrClear
  612.     1 1  TOC_call  ;        immediate
  613.  
  614. : %_MoveHHi
  615.     1 0  TOC_call  ;        immediate
  616.     
  617. : %_HLock
  618.     1 0  TOC_call  ;        immediate
  619.  
  620. : %_MakeDataExecutable
  621.     2 0  TOC_call  ;        immediate
  622.  
  623. : %_BlockMove
  624.     3 0  TOC_call  ;        immediate
  625.  
  626. : %_ExitToShell
  627.     0 0  TOC_call  ;        immediate
  628.  
  629. : %_InitGraf
  630.     1 0  TOC_call  ;        immediate
  631.  
  632. : %_InitFonts
  633.     0 0  TOC_call  ;        immediate
  634.  
  635. : %_InitWindows
  636.     0 0  TOC_call  ;        immediate
  637.  
  638. : %_TeInit
  639.     0 0  TOC_call  ;        immediate
  640.  
  641. : %_InitMenus
  642.     0 0  TOC_call  ;        immediate
  643.  
  644. : %_InitCursor
  645.     0 0  TOC_call  ;        immediate
  646.  
  647. : %_AEInstallEventHandler
  648.     5 1  TOC_call  ;        immediate
  649.  
  650. : %_GetNewWindow
  651.     3 1  TOC_call  ;        immediate
  652.     
  653. : %_SetPort
  654.     1 0  TOC_call  ;        immediate
  655.  
  656. : %_NewRgn
  657.     0 1  TOC_call  ;        immediate
  658.     
  659. : %_TextMode
  660.     1 0  TOC_call  ;        immediate
  661.  
  662. : %_SysBeep
  663.     1 0  TOC_call  ;        immediate
  664.  
  665.  
  666. : %_MaxApplZone
  667.     0 0  TOC_call  ;        immediate
  668.  
  669.  
  670. (*    INIT_RELOCS adds all the relocation ops to the loader section.  Here's where
  671.     we tell the PEF loader how resolve our imported symbols, etc.
  672. *)
  673.  
  674. : INIT_RELOCS
  675.     reset: export_relocs
  676.     $ 00010000    +L: relocs            \ these are sect 1 relocs
  677.     len: export_relocs 2/  2+
  678.                 +L: relocs            \ there are 2 of them, plus however many 
  679.                                     \  export relocs there are
  680.     0            +L: relocs            \ relocs offs = 0
  681.  
  682.     $ 4A00  #imported_symbols 1- or
  683.                 +W: relocs            \ RelocImportRun n - TOC entries for our n 
  684.                                     \  imported symbols
  685.  
  686.     $ 4600        +W: relocs            \ RelocTVector8 1 - this will update our entry
  687.                                     \  point descriptor.  See comment below.
  688.     export_relocs  $add: relocs        \ Add the export relocs, if any
  689. ;
  690.  
  691. (*    Note on how our initial entry point is worked out:
  692.     
  693.     Our entry point descriptor (2 words) starts out as all zero, because we
  694.     initially erase the TOC area (which starts at data_start).  The reloc
  695.     opcode RelocTVector8 above, adds the value "sectionC" to the first word,
  696.     and "sectionD" to the second, as described in the PEF spec.  These
  697.     two values are initialized to the start of the code and data sections
  698.     respectively at load time, and since we don't alter them with any earlier 
  699.     reloc ops, that's what they'll be when RelocTVector8 grabs them.  Thus
  700.     our entry point descriptor will be updated to: ( <start of code>, <start of
  701.     data> ) which means that when we start up, rTOC will be set to the start
  702.     of the data area, and execution will begin at the start of the code
  703.     area.  This is exactly what we want.
  704.     
  705.     If we later decide to start at some offset into the code area, I presume
  706.     that at PEF time we'll need to put the offset in the word at location
  707.     [ data_start entry_point_TOC_offset + ]
  708.     and this should be appropriately updated by the RelocTVector8 op.
  709. *)
  710.  
  711.  
  712. (*    INIT_CODE_SECTION initializes the code section.  code_start and code_size
  713.     are already set up.  We just have to initialize the extra info block.  We
  714.     can put whatever we need in this block.  It's not part of the PEF spec -
  715.     we just use it to pass Mops info to the new app at startup time.  This
  716.     block starts straight after the initial branch, at code_start + 4.  Its 
  717.     size is given by the constant info_block_size , so if we add extra fields, 
  718.     remember to adjust the constant.  It gets used by GO to allot the space at 
  719.     the beginning of the code section before PPC compilation starts.
  720.     
  721.     Here's the format of the info block - note that this MUST AGREE with
  722.     what setup expects!
  723.    
  724. ent pt offset      length        what it is
  725.  
  726.     0            4 bytes        initial branch
  727.     4            4 bytes        code size
  728.     8            4 bytes        data size
  729.     12            4 bytes        displacement from code_start to nuc_code_start
  730.                                 (i.e. code generator code size)
  731.     16            4 bytes        displacement from data_start to nuc_data_start
  732.                                 (i.e. code generator data size)
  733.     20            32 bytes    initial CONTEXT
  734.     52             4 bytes    flags
  735.     56             4 bytes    #bytes chopped from bottom of seg 8
  736.     60             4 bytes    #bytes chopped from bottom of seg 9
  737.     64             4 bytes    total code size (including spare room)
  738.     68             4 bytes    total data size (including spare room)
  739.     72             8 bytes    spare
  740.  
  741.         total: 80 bytes.
  742.  
  743. *)
  744.  
  745. variable    dummy_len
  746.  
  747.  
  748. : FIX_THREAD  { thread# \ thread_addr last_lfa link lfa -- }
  749.  
  750.     thread# dummy_len c!                \ fake a "length byte" for THREAD
  751.     dummy_len thread  -> thread_addr    \ addr of thread start in CONTEXT
  752.     
  753.     thread_addr displace  -> lfa        \ addr of first link field in thread,
  754.                                         \  in CONTEXT
  755.     lfa
  756.     code_start 20 + thread# 4* +
  757.     displ!                                \ store in new CONTEXT
  758.  
  759.     lfa -> last_lfa
  760.     BEGIN
  761.         last_lfa @  -> link                \ save link to see if it changes
  762.         last_lfa displace  -> lfa        \ chain back
  763.  
  764.         BEGIN                            \ loop over any links below chop_here
  765.             lfa
  766.             IF        lfa chop_here u<
  767.             ELSE    false    \ end inner loop
  768.             THEN
  769.         WHILE
  770.             lfa displace  -> lfa
  771.         REPEAT
  772.         
  773.         lfa
  774.         IF        lfa last_lfa  displ!
  775.         ELSE    0  last_lfa !
  776.         THEN
  777.     
  778.         last_lfa @  link <>
  779.         IF
  780.             link +L: $threads  last_lfa +L: $threads
  781.         THEN
  782.         lfa dup -> last_lfa
  783.     NUNTIL
  784. ;
  785.  
  786.  
  787. : ADD_CONTEXT
  788.     new: $threads                        \ init string to save orig threads
  789.     #threads  FOR  i fix_thread  NEXT
  790. ;
  791.  
  792.  
  793. : RESTORE_THREADS
  794.     reset: $threads
  795.     BEGIN    len: $threads
  796.     WHILE    nxtL: $threads  ( orig link )  nxtL: $threads ( where it went )  !
  797.     REPEAT
  798.     release: $threads
  799. ;
  800.  
  801.  
  802. : set_seg_sizes  { \ ^ST len -- }
  803.     0 -> seg_code_size  0 -> seg_data_size
  804.     max_segs 2
  805.     DO    i  8 *  segTable +  -> ^ST
  806.         ^ST c@ 1 and
  807.         IF            \ we need to install this one
  808.             ^ST @ $ 00ffffff and #align4  -> len
  809.             i 1 and
  810.             NIF        \ it's code
  811.                 len ++> seg_code_size
  812.             ELSE
  813.                 len ++> seg_data_size
  814.             THEN
  815.         THEN
  816.     LOOP
  817. ;
  818.  
  819. : INIT_CODE_SECTION  { \ flags sv_code_start sv_data_start -- }
  820.  
  821.     0 -> flags  code_start -> chop_here
  822.     instld?
  823.     IF
  824.         1 -> flags
  825.         shared_lib? IF  2 or> flags  THEN
  826.         code_start -> sv_code_start
  827.         nuc_code_start info_block_size -
  828.         dup -> code_start  info_block_size erase
  829.         nuc_code_start -> chop_here
  830.         CDP nuc_code_start - 256 +  -> main_code_size
  831.         code_start sv_code_start -  code_start 56 + !
  832.  
  833.         data_start -> sv_data_start
  834.         nuc_data_start TOC_size -
  835.         dup -> data_start  TOC_size erase
  836.         DP nuc_data_start - 256 +  -> main_data_size
  837.         data_start sv_data_start -  code_start 60 + !
  838.         
  839.         set_seg_sizes        \ initialize seg_code_size and seg_data_size
  840.         
  841.     \ now we must adjust the initial branch and put it at the start
  842.     \  of the (shortened) code section):
  843.     
  844.         sv_code_start @  $ 03ffffff and
  845.         sv_code_start +  code_start -  $ 48000000 or
  846.         code_start !
  847.  
  848.     THEN
  849.  
  850.     main_code_size    code_start  4 + !        \ code size
  851.     main_data_size    code_start  8 + !        \ data size
  852.  
  853.     main_code_size spare_code_size +  code_start 64 + !
  854.     main_data_size spare_data_size +  code_start 68 + !
  855.     
  856.     nuc_code_start code_start -
  857.                 code_start 12 + !            \ displ to nuc_code_start
  858.     nuc_data_start data_start -
  859.                 code_start 16 + !            \ offset to last extern
  860.     flags        code_start 52 + !            \ flags
  861.     add_context                                \ adds 32 bytes
  862. ;
  863.  
  864.  
  865. : INIT_DATA_SECTION
  866. ;        \ data_start and main_data_size are set up already
  867.  
  868. : INIT_LOADER_SECTION
  869.     clear: export_hash_table
  870.     init_symbols
  871.     setup: export_hash_table  
  872.     init_relocs
  873. ;
  874.  
  875.  
  876. : SET_OFFSETS  { \ relocsOffs stringsOffs hashSlotTblOffs -- }
  877.  
  878.     0 -> container_offs
  879.     $ 80  -> ldr_offs
  880.  
  881.     length: loader_header
  882.     #align4  length: import_files_subsection  +
  883.     #align4  size: ldr_import_sym_tbl  +
  884.     #align4  dup 12 +  -> relocsOffs        \ reloc header is always 12 bytes
  885.     size: relocs  +
  886.     #align4  dup -> stringsOffs
  887.     size: loader_strings +
  888.     #align4  dup -> hashSlotTblOffs
  889.     hash_info_len +
  890.     -> ldr_size    
  891.  
  892.     relocsOffs stringsOffs hashSlotTblOffs
  893.     1 ( data section )
  894.     init: loader_header
  895.  
  896.     ldr_offs ldr_size +  #align16  -> code_offs
  897.     code_offs main_code_size + seg_code_size +  #align16
  898.     -> data_offs
  899.     
  900.     0 >kind: code_sect_hdr
  901.     1 >kind: data_sect_hdr
  902.     4 >kind: loader_sect_hdr
  903.     
  904.     code_offs  main_code_size seg_code_size +  dup  init: code_sect_hdr
  905.     data_offs  main_data_size seg_data_size +  dup  init: data_sect_hdr
  906.     ldr_offs  ldr_size dup  init: loader_sect_hdr
  907. ;
  908.  
  909.  
  910. syscall CreateResFile
  911.  
  912. \ note: syscall OpenResFile and syscall CloseResFile have already been done,
  913. \  and because they have a different meaning in Mops, we've renamed
  914. \  them to ZpenResFile and ZloseResFile.
  915.  
  916.  
  917.  
  918. : add_resources  { RF_open? installing? \ refNo -- }
  919.  
  920. \ first we open the resource fork if it's not open already
  921.     RF_open?
  922.     NIF
  923.         getName: ffcb  str255
  924.         CreateResFile  resChk
  925.         buf255  ZpenResFile  -> refNo  resChk
  926.     THEN
  927.     
  928. \ now we add the 'cfrg' resource:
  929.     new: $cfrg
  930.     my_cfrg  length: my_cfrg  add: $cfrg
  931.     size: $cfrg  getName: ffcb nip +  $ 1D -    \ len of info record section
  932.     +W: $cfrg
  933.     getName: ffcb  dup +c: $cfrg  add: $cfrg
  934.     $cfrg @  dstres !        \ both are subclassed from Handle!
  935.     'type cfrg  0  set: dstres
  936.     nullOSstr  addRes: dstres  resChk
  937.     
  938.     installing?
  939.     NIF            \ If installing, zInstlMod decides about these
  940.         'type WIND  256  copyRes        \ otherwise we need fWind
  941.         'type BNDL  129  copyRes        \ and the BNDL
  942.         133 128 DO                        \ and the FREFs, icl8's and ICN#s
  943.             'type FREF  i  copyRes        \  (128 - 132)
  944.             'type icl8  i  copyRes
  945.             'type ICN#  i  copyRes
  946.         LOOP
  947.         'type ics8  128  copyRes        \ and ics8 128
  948.         
  949.     \ and also the new version resource which has a "type" that is the
  950.     \ same as the sig, and ID 0.
  951.  
  952.         'type Mopp  0  set: dstRes
  953.         50 getstring                \ our version string
  954.         refNo UseResFile            \ need to restore dest res file
  955.         dup 1+ align  new: dstRes
  956.         str255  ptr: dstRes  over  c@ 1+ cMove
  957.         nullOSstr  addRes: dstRes
  958.     THEN
  959.     
  960.     'type SIZE  -1     copyRes        \ copy SIZE -1
  961.  
  962.     RF_open?
  963.     NIF
  964.         refNo ZloseResFile
  965.     THEN
  966. ;
  967. \ note we mustn't release: $cfrg since the handle now belongs to the
  968. \ Resource Manager!
  969.  
  970.  
  971. : write_segs  { 1st_seg# \ ^ST len cnt -- }
  972.     0 -> cnt
  973.     max_segs 1st_seg#
  974.     DO    i  8 *  segTable +  -> ^ST
  975.         ^ST c@ 1 and
  976.         IF            \ we need to install this one
  977.             ^ST @ $ 00ffffff and #align4  -> len
  978.             ^ST 4+ @  len  write_to_container
  979.             1 ++> cnt
  980.         THEN
  981.     2 +LOOP
  982. ;
  983.  
  984.  
  985. : (wp)  { RF_open? installing? \ svCL svDL -- }
  986.                 \ This is the word that writes out the new PEF file.
  987.                 \  fFcb must be already set up and open.  If the resource
  988.                 \  fork is open, we pass in true.
  989.  
  990.     installing? -> instld?            \ set global flag in new app
  991. \    shared_lib? if  true -> instld?  then
  992.     code_limit -> svCL  data_limit -> svDL
  993.     CDP -> code_limit  DP  -> data_limit
  994.     code_limit  code_start -  -> main_code_size        \ will get changed if we're installing
  995.     data_limit  data_start -  -> main_data_size        \ ditto
  996.  
  997.     installing? IF  load_mods  THEN        \ load mods needed in installed app
  998.  
  999.     cr
  1000.     ." code size (hex): "  main_code_size seg_code_size + .h  cr
  1001.     ." data size (hex): "  main_data_size seg_data_size + .h  cr
  1002.  
  1003.     new: ldr_import_sym_tbl
  1004.     new: relocs  new: export_relocs
  1005.     new: loader_strings
  1006.     
  1007.     classinit: export_key_table
  1008.     classinit: exported_symbol_table
  1009.  
  1010.     init_code_section            \ must come first as it resets code_start and data_start
  1011.                                 \  if we're installing
  1012.     init_loader_section
  1013.     installing? IF  set_seg_sizes  THEN
  1014.  
  1015.     init_data_section
  1016. \    init_loader_section
  1017.     set_offsets
  1018.     setTimeStamp: PEF_header
  1019.  
  1020. \ write PEF header:
  1021.     PEF_header            write_obj
  1022.     code_sect_hdr        write_obj
  1023.     data_sect_hdr        write_obj
  1024.     loader_sect_hdr        write_obj
  1025.  
  1026.     pad_bytes 4  write_to_container            \ dummy global symbol table
  1027.  
  1028. \ loader section:
  1029.     loader_header                write_obj
  1030.     import_files_subsection        write_obj
  1031.     all: ldr_import_sym_tbl        write_to_container
  1032.     all: relocs                    write_to_container    4  align_in_container
  1033.     all: loader_strings            write_to_container    4  align_in_container
  1034.     write: export_hash_table
  1035.  
  1036. \ code section:
  1037.     16 align_in_container
  1038.     code_start  main_code_size  write_to_container
  1039.     installing?
  1040.     IF  2 write_segs  THEN                \ add module code segs
  1041.  
  1042. \ data section:
  1043.     16 align_in_container
  1044.     data_start  TOC_size erase            \ TOC area must be initially zero!
  1045.  
  1046.     data_start  main_data_size  write_to_container
  1047.     installing?
  1048.     IF  3 write_segs  THEN                \ add module data segs
  1049.  
  1050.     release: ldr_import_sym_tbl
  1051.     release: relocs  release: export_relocs
  1052.     release: loader_strings
  1053.     
  1054.     RF_open? installing? add_resources
  1055.     RF_open? NIF  close: ffcb drop  THEN
  1056. \    RF_open? add_resources
  1057.     restore_threads
  1058.     svCL -> code_limit  svDL -> data_limit
  1059. ;
  1060.  
  1061.  
  1062. : CREATE_OUTPF?  ( addr len true | false -- b )
  1063.     clear: ffcb
  1064.     IF    name: ffcb
  1065.     ELSE
  1066.         " new PEF file:"  " PowerMops" stdPut: ffcb  NIF  false  EXIT  THEN
  1067.     THEN
  1068.  
  1069.     open: ffcb NIF  close: ffcb drop  delete: ffcb drop  THEN
  1070.     create: ffcb  OK?
  1071.     addr: ffcb 18 + @                \ Name pointer - get final app name out of ffcb
  1072.     count  32 min  myDocName place
  1073.     shared_lib?
  1074.     IF        'type shlb  'type cfmg
  1075.     ELSE    'type APPL  'type Mopp  
  1076.     THEN  set: ffcb
  1077.     $ 21  addr: ffcb  $ 28 + c!            \ Set Bundle bit
  1078.     setFileInfo: ffcb  OK?
  1079.  
  1080.     true  ;
  1081.  
  1082.  
  1083.  
  1084. : (write_pef)  ( addr len true | false )
  1085.         \ If the flag is true, we saved with the passed-in name.
  1086.         \ Otherwise we put up a dialog for the output file.
  1087.  
  1088.     create_outpf?  0EXIT
  1089.     false  false  (wp)
  1090. ;
  1091.  
  1092.  
  1093. : WRITE_PEF        false (write_pef)  ;
  1094.  
  1095. : SAVE
  1096.     bl word count
  1097.     2dup cr cr ." Saved : " type
  1098.     true (write_pef)
  1099. ;
  1100.  
  1101. \ shared library testing
  1102.  
  1103. : SLTEST
  1104.     true -> shared_lib?
  1105.     bl word count
  1106.     true create_outpf?  0EXIT
  1107.     false  true  (wp)
  1108. ;
  1109.     
  1110. :f I/O_err
  1111.     ." I/O err " .  cr
  1112.     close: ffcb drop
  1113. ;f
  1114.  
  1115. endload
  1116.  
  1117. : test
  1118.     16 0 DO
  1119.         i select: export_key_table
  1120.         len: export_key_table
  1121.         IF  dump: export_key_table  THEN
  1122.     LOOP
  1123.     cr
  1124.     16 0 DO
  1125.         i select: exported_symbol_table
  1126.         len: exported_symbol_table
  1127.         IF  dump: exported_symbol_table  THEN
  1128.     LOOP
  1129.     cr cr
  1130.     all: $testxx  dump
  1131. ;
  1132.